The prompt and base code for this project can be found on Datacamp. The basis of this is to explore the volatility of Zero Coupon Bond Yields (from year maturities 1-30) and see how that has changed since the 1960’s. Below, I loaded the necessary librares and did some data exploration of the time series data obtained from Quandl. This was obtained making an API call.

Necessary packages


defaultW <- getOption("warn") 

options(warn = -1) 

library(dygraphs)
library(Quandl)
library(dplyr)
library(rugarch)
library(plotly)
library(RColorBrewer)

options(warn = defaultW)
#get dataset, filter for coronavirus dates
df <- Quandl("FED/SVENY", api_key="15cxBvvbCzucYDswsDfJ")
covid_dates <- subset(df, Date > '2020-01-01' & Date < '2020-08-20')

str(df)
'data.frame':   14755 obs. of  31 variables:
 $ Date   : Date, format: "2020-08-14" "2020-08-13" "2020-08-12" "2020-08-11" ...
 $ SVENY01: num  0.157 0.162 0.162 0.159 0.146 ...
 $ SVENY02: num  0.157 0.171 0.163 0.155 0.135 ...
 $ SVENY03: num  0.197 0.215 0.202 0.187 0.161 ...
 $ SVENY04: num  0.26 0.278 0.261 0.24 0.209 ...
 $ SVENY05: num  0.334 0.351 0.331 0.304 0.268 ...
 $ SVENY06: num  0.412 0.426 0.404 0.373 0.332 ...
 $ SVENY07: num  0.491 0.502 0.478 0.443 0.398 ...
 $ SVENY08: num  0.568 0.577 0.551 0.512 0.463 ...
 $ SVENY09: num  0.643 0.649 0.621 0.58 0.527 ...
 $ SVENY10: num  0.715 0.717 0.688 0.644 0.589 ...
 $ SVENY11: num  0.784 0.783 0.752 0.706 0.649 ...
 $ SVENY12: num  0.849 0.846 0.813 0.766 0.706 ...
 $ SVENY13: num  0.911 0.906 0.872 0.823 0.762 ...
 $ SVENY14: num  0.971 0.964 0.927 0.878 0.815 ...
 $ SVENY15: num  1.028 1.019 0.98 0.93 0.866 ...
 $ SVENY16: num  1.082 1.071 1.031 0.98 0.915 ...
 $ SVENY17: num  1.134 1.121 1.08 1.028 0.962 ...
 $ SVENY18: num  1.18 1.17 1.13 1.07 1.01 ...
 $ SVENY19: num  1.23 1.22 1.17 1.12 1.05 ...
 $ SVENY20: num  1.28 1.26 1.21 1.16 1.09 ...
 $ SVENY21: num  1.32 1.3 1.25 1.2 1.13 ...
 $ SVENY22: num  1.36 1.34 1.29 1.24 1.17 ...
 $ SVENY23: num  1.4 1.38 1.33 1.28 1.21 ...
 $ SVENY24: num  1.44 1.42 1.37 1.31 1.25 ...
 $ SVENY25: num  1.48 1.45 1.4 1.35 1.28 ...
 $ SVENY26: num  1.52 1.49 1.43 1.38 1.31 ...
 $ SVENY27: num  1.55 1.52 1.46 1.41 1.34 ...
 $ SVENY28: num  1.58 1.55 1.5 1.44 1.38 ...
 $ SVENY29: num  1.61 1.58 1.52 1.47 1.4 ...
 $ SVENY30: num  1.64 1.61 1.55 1.5 1.43 ...
 - attr(*, "freq")= chr "daily"

Plotting daily estimates for yall zero coupon yields for 2020

dfasxts <- as.xts(x = df[, -1], order.by = df$Date)
covid_dates <- as.xts(x = covid_dates[, -1], order.by = covid_dates$Date)
dygraph(covid_dates, main = "All Zero Coupon Yields (1-30) 2020", ylab = "Value") %>%
            dyAxis('x', axisLabelFontSize = 12) %>%
            dyRangeSelector()
df$Date <- as.Date(df$Date)
df$year <- format(as.Date(df$Date, format="%m/%d/%Y"),"%Y")
df <- select(df, -Date)
df <- na.omit(df)

df <- df %>%
  group_by(year) %>%
  summarise_all(mean)
  
SVENY01 <- df$SVENY01
SVENY10 <- df$SVENY10
SVENY30 <- df$SVENY30


data <- data.frame(df, SVENY01, SVENY10, SVENY30)
data <- select(data, year, SVENY01, SVENY10, SVENY30)
fig <- plot_ly(data, x = data$year, y = ~SVENY01, name = 'SVENY01', type = 'scatter', mode = 'lines + markers') 
fig <- fig %>% add_trace(y = ~SVENY10, name = 'SVENY10', mode = 'lines + markers') 
fig <- fig %>% add_trace(y = ~SVENY30, name = 'SVENY30', mode = 'lines + markers')
fig <- fig %>% layout(title = "",
         xaxis = list(title = "year"),
         yaxis = list (title = "value"))

1, 10, and 30 year maturity bond yield averages across time

fig

Bond yield heat map

row.names(df) <- df$year
Setting row names on a tibble is deprecated.
df <- select(df, -year)
df_matrix <- data.matrix(df)

df_heatmap <- heatmap(df_matrix, Rowv=NA, Colv=NA, col = brewer.pal(6, "Greys"), scale="column", margins=c(4,1), main = "Heatmap")

# plotting the evaluation of bond yields
library(viridisLite)
yields <- dfasxts
plot.type <- "single"
plot.palette <- magma(n = 30)
asset.names <- colnames(dfasxts)
plot.zoo(x = dfasxts, plot.type = "single", col = plot.palette, ylab = "", xlab = "")
legend(x = "topleft", legend = asset.names, col = plot.palette, cex = 0.45, lwd = 3)

dfasxts_d <- diff(dfasxts)

plot.zoo(x = dfasxts_d, plot.type = "multiple", ylim = c(-0.5, 0.5), cex.axis = 0.7, ylab = 1:30, col = plot.palette, main = "", xlab = "")

dfasxts <- dfasxts_d["2000/",]
x_1 <- dfasxts[,"SVENY01"]
x_20 <- dfasxts[, "SVENY20"]

# Plot the autocorrelations of the yield changes)
par(mar=c(5.1, 4.1, 4.1, 2.1))
par(mfrow=c(2,2))
acf_1 <- acf(x_1)
acf_20 <- acf(x_20)

# Plot the autocorrelations of the absolute changes of yields
acf_abs_1 <- acf(abs(x_1))
acf_abs_20 <- acf(abs(x_20))

NA
NA

spec <- ugarchspec(distribution.model = "sstd")


fit_1 <- ugarchfit(x_1, spec = spec)


vol_1 <- sigma(fit_1)
res_1 <- scale(residuals(fit_1, standardize = TRUE)) * sd(x_1) + mean(x_1)


merge_1 <- merge.xts(x_1, vol_1, res_1)
plot.zoo(merge_1, xlab = "Year")


####################

fit_20 <- ugarchfit(x_20, spec = spec)


vol_20 <- sigma(fit_20)
res_20 <- scale(residuals(fit_20, standardize = TRUE)) * sd(x_20) + mean(x_20)


merge_20 <- merge.xts(x_20, vol_20, res_20)
plot.zoo(merge_20, xlab = "Year")

par(mar=c(5.1, 4.1, 4.1, 2.1))
par(mfrow=c(2,1))
hist(res_1)
hist(res_20)

ugarchspec()

*---------------------------------*
*       GARCH Model Spec          *
*---------------------------------*

Conditional Variance Dynamics   
------------------------------------
GARCH Model     : sGARCH(1,1)
Variance Targeting  : FALSE 

Conditional Mean Dynamics
------------------------------------
Mean Model      : ARFIMA(1,0,1)
Include Mean        : TRUE 
GARCH-in-Mean       : FALSE 

Conditional Distribution
------------------------------------
Distribution    :  norm 
Includes Skew   :  FALSE 
Includes Shape  :  FALSE 
Includes Lambda :  FALSE 
density_x_1 <- density(x_1)
density_res_1 <- density(res_1)


plot(density_x_1)
lines(density_res_1, col = "red")


norm_dist <- dnorm(seq(-0.4, 0.4, by = .01), mean = mean(x_1), sd = sd(x_1))
lines(seq(-0.4, 0.4, by = .01), 
      norm_dist, 
      col = "darkblue"
     )

# Add legend
legend <- c("Before GARCH", "After GARCH", "Normal distribution")
legend("topleft", legend = legend, 
       col = c("black", "red", "darkblue"), lty=c(1,1))

distribution <- qnorm


qqnorm(x_1, ylim = c(-0.5, 0.5))
qqline(x_1, distribution = distribution, col = "darkgreen")


par(new=TRUE)
qqnorm(res_1 * 0.614256270265139, col = "red", ylim = c(-0.5, 0.5))
qqline(res_1 * 0.614256270265139, distribution = distribution, col = "darkgreen")
legend("topleft", c("Before GARCH", "After GARCH"), col = c("black", "red"), pch=c(1,1))

Conclusion

Garch modeling brought the residuals closer to normal distribution. Year 1 yield deviates more from a normally distributed white noise process than a 20 year yield.

LS0tDQp0aXRsZTogIk1vZGVsaW5nIHRoZSBWb2xhdGlsaXR5IG9mIFUuUyBCb25kIFlpZWxkcyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBkZl9wcmludDogcGFnZWQNCi0tLQ0KIyMjIFRoZSBwcm9tcHQgYW5kIGJhc2UgY29kZSBmb3IgdGhpcyBwcm9qZWN0IGNhbiBiZSBmb3VuZCBvbiBEYXRhY2FtcC4gVGhlIGJhc2lzIG9mIHRoaXMgaXMgdG8gZXhwbG9yZSB0aGUgdm9sYXRpbGl0eSBvZiBaZXJvIENvdXBvbiBCb25kIFlpZWxkcyAoZnJvbSB5ZWFyIG1hdHVyaXRpZXMgMS0zMCkgYW5kIHNlZSBob3cgdGhhdCBoYXMgY2hhbmdlZCBzaW5jZSB0aGUgMTk2MCdzLiBCZWxvdywgSSBsb2FkZWQgdGhlIG5lY2Vzc2FyeSBsaWJyYXJlcyBhbmQgZGlkIHNvbWUgZGF0YSBleHBsb3JhdGlvbiBvZiB0aGUgdGltZSBzZXJpZXMgZGF0YSBvYnRhaW5lZCBmcm9tIFF1YW5kbC4gVGhpcyB3YXMgb2J0YWluZWQgbWFraW5nIGFuIEFQSSBjYWxsLiANCg0KDQojIyBOZWNlc3NhcnkgcGFja2FnZXMNCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQoNCmRlZmF1bHRXIDwtIGdldE9wdGlvbigid2FybiIpIA0KDQpvcHRpb25zKHdhcm4gPSAtMSkgDQoNCmxpYnJhcnkoZHlncmFwaHMpDQpsaWJyYXJ5KFF1YW5kbCkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KHJ1Z2FyY2gpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoUkNvbG9yQnJld2VyKQ0KDQpvcHRpb25zKHdhcm4gPSBkZWZhdWx0VykNCg0KDQpgYGANCg0KDQpgYGB7cn0NCiNnZXQgZGF0YXNldCwgZmlsdGVyIGZvciBjb3JvbmF2aXJ1cyBkYXRlcw0KZGYgPC0gUXVhbmRsKCJGRUQvU1ZFTlkiLCBhcGlfa2V5PSIxNWN4QnZ2YkN6dWNZRHN3c0RmSiIpDQpjb3ZpZF9kYXRlcyA8LSBzdWJzZXQoZGYsIERhdGUgPiAnMjAyMC0wMS0wMScgJiBEYXRlIDwgJzIwMjAtMDgtMjAnKQ0KDQpzdHIoZGYpDQpgYGANCg0KIyMjIFBsb3R0aW5nIGRhaWx5IGVzdGltYXRlcyBmb3IgeWFsbCB6ZXJvIGNvdXBvbiB5aWVsZHMgZm9yIDIwMjANCmBgYHtyfQ0KZGZhc3h0cyA8LSBhcy54dHMoeCA9IGRmWywgLTFdLCBvcmRlci5ieSA9IGRmJERhdGUpDQpjb3ZpZF9kYXRlcyA8LSBhcy54dHMoeCA9IGNvdmlkX2RhdGVzWywgLTFdLCBvcmRlci5ieSA9IGNvdmlkX2RhdGVzJERhdGUpDQpkeWdyYXBoKGNvdmlkX2RhdGVzLCBtYWluID0gIkFsbCBaZXJvIENvdXBvbiBZaWVsZHMgKDEtMzApIDIwMjAiLCB5bGFiID0gIlZhbHVlIikgJT4lDQogICAgICAgICAgICBkeUF4aXMoJ3gnLCBheGlzTGFiZWxGb250U2l6ZSA9IDEyKSAlPiUNCiAgICAgICAgICAgIGR5UmFuZ2VTZWxlY3RvcigpDQpgYGANCg0KDQpgYGB7cn0NCmRmJERhdGUgPC0gYXMuRGF0ZShkZiREYXRlKQ0KZGYkeWVhciA8LSBmb3JtYXQoYXMuRGF0ZShkZiREYXRlLCBmb3JtYXQ9IiVtLyVkLyVZIiksIiVZIikNCmRmIDwtIHNlbGVjdChkZiwgLURhdGUpDQpkZiA8LSBuYS5vbWl0KGRmKQ0KDQpkZiA8LSBkZiAlPiUNCiAgZ3JvdXBfYnkoeWVhcikgJT4lDQogIHN1bW1hcmlzZV9hbGwobWVhbikNCmBgYA0KDQoNCmBgYHtyfQ0KICANClNWRU5ZMDEgPC0gZGYkU1ZFTlkwMQ0KU1ZFTlkxMCA8LSBkZiRTVkVOWTEwDQpTVkVOWTMwIDwtIGRmJFNWRU5ZMzANCg0KDQpkYXRhIDwtIGRhdGEuZnJhbWUoZGYsIFNWRU5ZMDEsIFNWRU5ZMTAsIFNWRU5ZMzApDQpkYXRhIDwtIHNlbGVjdChkYXRhLCB5ZWFyLCBTVkVOWTAxLCBTVkVOWTEwLCBTVkVOWTMwKQ0KZmlnIDwtIHBsb3RfbHkoZGF0YSwgeCA9IGRhdGEkeWVhciwgeSA9IH5TVkVOWTAxLCBuYW1lID0gJ1NWRU5ZMDEnLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzICsgbWFya2VycycpIA0KZmlnIDwtIGZpZyAlPiUgYWRkX3RyYWNlKHkgPSB+U1ZFTlkxMCwgbmFtZSA9ICdTVkVOWTEwJywgbW9kZSA9ICdsaW5lcyArIG1hcmtlcnMnKSANCmZpZyA8LSBmaWcgJT4lIGFkZF90cmFjZSh5ID0gflNWRU5ZMzAsIG5hbWUgPSAnU1ZFTlkzMCcsIG1vZGUgPSAnbGluZXMgKyBtYXJrZXJzJykNCmZpZyA8LSBmaWcgJT4lIGxheW91dCh0aXRsZSA9ICIiLA0KICAgICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gInllYXIiKSwNCiAgICAgICAgIHlheGlzID0gbGlzdCAodGl0bGUgPSAidmFsdWUiKSkNCg0KYGBgDQojIyMgMSwgMTAsIGFuZCAzMCB5ZWFyIG1hdHVyaXR5IGJvbmQgeWllbGQgYXZlcmFnZXMgYWNyb3NzIHRpbWUNCg0KYGBge3J9DQpmaWcNCmBgYA0KIyMjIEJvbmQgeWllbGQgaGVhdCBtYXANCmBgYHtyfQ0Kcm93Lm5hbWVzKGRmKSA8LSBkZiR5ZWFyDQpkZiA8LSBzZWxlY3QoZGYsIC15ZWFyKQ0KZGZfbWF0cml4IDwtIGRhdGEubWF0cml4KGRmKQ0KDQpkZl9oZWF0bWFwIDwtIGhlYXRtYXAoZGZfbWF0cml4LCBSb3d2PU5BLCBDb2x2PU5BLCBjb2wgPSBicmV3ZXIucGFsKDYsICJHcmV5cyIpLCBzY2FsZT0iY29sdW1uIiwgbWFyZ2lucz1jKDQsMSksIG1haW4gPSAiSGVhdG1hcCIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KIyBwbG90dGluZyB0aGUgZXZhbHVhdGlvbiBvZiBib25kIHlpZWxkcw0KbGlicmFyeSh2aXJpZGlzTGl0ZSkNCnlpZWxkcyA8LSBkZmFzeHRzDQpwbG90LnR5cGUgPC0gInNpbmdsZSINCnBsb3QucGFsZXR0ZSA8LSBtYWdtYShuID0gMzApDQphc3NldC5uYW1lcyA8LSBjb2xuYW1lcyhkZmFzeHRzKQ0KcGxvdC56b28oeCA9IGRmYXN4dHMsIHBsb3QudHlwZSA9ICJzaW5nbGUiLCBjb2wgPSBwbG90LnBhbGV0dGUsIHlsYWIgPSAiIiwgeGxhYiA9ICIiKQ0KbGVnZW5kKHggPSAidG9wbGVmdCIsIGxlZ2VuZCA9IGFzc2V0Lm5hbWVzLCBjb2wgPSBwbG90LnBhbGV0dGUsIGNleCA9IDAuNDUsIGx3ZCA9IDMpDQpgYGANCg0KYGBge3J9DQpkZmFzeHRzX2QgPC0gZGlmZihkZmFzeHRzKQ0KDQpwbG90Lnpvbyh4ID0gZGZhc3h0c19kLCBwbG90LnR5cGUgPSAibXVsdGlwbGUiLCB5bGltID0gYygtMC41LCAwLjUpLCBjZXguYXhpcyA9IDAuNywgeWxhYiA9IDE6MzAsIGNvbCA9IHBsb3QucGFsZXR0ZSwgbWFpbiA9ICIiLCB4bGFiID0gIiIpDQoNCmBgYA0KDQpgYGB7cn0NCmRmYXN4dHMgPC0gZGZhc3h0c19kWyIyMDAwLyIsXQ0KeF8xIDwtIGRmYXN4dHNbLCJTVkVOWTAxIl0NCnhfMjAgPC0gZGZhc3h0c1ssICJTVkVOWTIwIl0NCg0KIyBQbG90IHRoZSBhdXRvY29ycmVsYXRpb25zIG9mIHRoZSB5aWVsZCBjaGFuZ2VzKQ0KcGFyKG1hcj1jKDUuMSwgNC4xLCA0LjEsIDIuMSkpDQpwYXIobWZyb3c9YygyLDIpKQ0KYWNmXzEgPC0gYWNmKHhfMSkNCmFjZl8yMCA8LSBhY2YoeF8yMCkNCg0KIyBQbG90IHRoZSBhdXRvY29ycmVsYXRpb25zIG9mIHRoZSBhYnNvbHV0ZSBjaGFuZ2VzIG9mIHlpZWxkcw0KYWNmX2Fic18xIDwtIGFjZihhYnMoeF8xKSkNCmFjZl9hYnNfMjAgPC0gYWNmKGFicyh4XzIwKSkNCg0KDQpgYGANCg0KDQoNCmBgYHtyfQ0KDQpzcGVjIDwtIHVnYXJjaHNwZWMoZGlzdHJpYnV0aW9uLm1vZGVsID0gInNzdGQiKQ0KDQoNCmZpdF8xIDwtIHVnYXJjaGZpdCh4XzEsIHNwZWMgPSBzcGVjKQ0KDQoNCnZvbF8xIDwtIHNpZ21hKGZpdF8xKQ0KcmVzXzEgPC0gc2NhbGUocmVzaWR1YWxzKGZpdF8xLCBzdGFuZGFyZGl6ZSA9IFRSVUUpKSAqIHNkKHhfMSkgKyBtZWFuKHhfMSkNCg0KDQptZXJnZV8xIDwtIG1lcmdlLnh0cyh4XzEsIHZvbF8xLCByZXNfMSkNCnBsb3Quem9vKG1lcmdlXzEsIHhsYWIgPSAiWWVhciIpDQoNCiMjIyMjIyMjIyMjIyMjIyMjIyMjDQoNCmZpdF8yMCA8LSB1Z2FyY2hmaXQoeF8yMCwgc3BlYyA9IHNwZWMpDQoNCg0Kdm9sXzIwIDwtIHNpZ21hKGZpdF8yMCkNCnJlc18yMCA8LSBzY2FsZShyZXNpZHVhbHMoZml0XzIwLCBzdGFuZGFyZGl6ZSA9IFRSVUUpKSAqIHNkKHhfMjApICsgbWVhbih4XzIwKQ0KDQoNCm1lcmdlXzIwIDwtIG1lcmdlLnh0cyh4XzIwLCB2b2xfMjAsIHJlc18yMCkNCnBsb3Quem9vKG1lcmdlXzIwLCB4bGFiID0gIlllYXIiKQ0KDQpgYGANCg0KYGBge3J9DQpwYXIobWFyPWMoNS4xLCA0LjEsIDQuMSwgMi4xKSkNCnBhcihtZnJvdz1jKDIsMSkpDQpoaXN0KHJlc18xKQ0KaGlzdChyZXNfMjApDQp1Z2FyY2hzcGVjKCkNCmBgYA0KDQoNCg0KYGBge3J9DQpkZW5zaXR5X3hfMSA8LSBkZW5zaXR5KHhfMSkNCmRlbnNpdHlfcmVzXzEgPC0gZGVuc2l0eShyZXNfMSkNCg0KDQpwbG90KGRlbnNpdHlfeF8xKQ0KbGluZXMoZGVuc2l0eV9yZXNfMSwgY29sID0gInJlZCIpDQoNCg0Kbm9ybV9kaXN0IDwtIGRub3JtKHNlcSgtMC40LCAwLjQsIGJ5ID0gLjAxKSwgbWVhbiA9IG1lYW4oeF8xKSwgc2QgPSBzZCh4XzEpKQ0KbGluZXMoc2VxKC0wLjQsIDAuNCwgYnkgPSAuMDEpLCANCiAgICAgIG5vcm1fZGlzdCwgDQogICAgICBjb2wgPSAiZGFya2JsdWUiDQogICAgICkNCg0KIyBBZGQgbGVnZW5kDQpsZWdlbmQgPC0gYygiQmVmb3JlIEdBUkNIIiwgIkFmdGVyIEdBUkNIIiwgIk5vcm1hbCBkaXN0cmlidXRpb24iKQ0KbGVnZW5kKCJ0b3BsZWZ0IiwgbGVnZW5kID0gbGVnZW5kLCANCiAgICAgICBjb2wgPSBjKCJibGFjayIsICJyZWQiLCAiZGFya2JsdWUiKSwgbHR5PWMoMSwxKSkNCmBgYA0KDQoNCmBgYHtyfQ0KZGlzdHJpYnV0aW9uIDwtIHFub3JtDQoNCg0KcXFub3JtKHhfMSwgeWxpbSA9IGMoLTAuNSwgMC41KSkNCnFxbGluZSh4XzEsIGRpc3RyaWJ1dGlvbiA9IGRpc3RyaWJ1dGlvbiwgY29sID0gImRhcmtncmVlbiIpDQoNCg0KcGFyKG5ldz1UUlVFKQ0KcXFub3JtKHJlc18xICogMC42MTQyNTYyNzAyNjUxMzksIGNvbCA9ICJyZWQiLCB5bGltID0gYygtMC41LCAwLjUpKQ0KcXFsaW5lKHJlc18xICogMC42MTQyNTYyNzAyNjUxMzksIGRpc3RyaWJ1dGlvbiA9IGRpc3RyaWJ1dGlvbiwgY29sID0gImRhcmtncmVlbiIpDQpsZWdlbmQoInRvcGxlZnQiLCBjKCJCZWZvcmUgR0FSQ0giLCAiQWZ0ZXIgR0FSQ0giKSwgY29sID0gYygiYmxhY2siLCAicmVkIiksIHBjaD1jKDEsMSkpDQpgYGANCg0KDQojIENvbmNsdXNpb24NCiMjIyMgR2FyY2ggbW9kZWxpbmcgYnJvdWdodCB0aGUgcmVzaWR1YWxzIGNsb3NlciB0byBub3JtYWwgZGlzdHJpYnV0aW9uLiBZZWFyIDEgeWllbGQgZGV2aWF0ZXMgbW9yZSBmcm9tIGEgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgd2hpdGUgbm9pc2UgcHJvY2VzcyB0aGFuIGEgMjAgeWVhciB5aWVsZC4g